--战斗对象相关
-- init 				初始化对象
-- setInitAttr 			设置默认属性
local RoleDefine = require("role.RoleDefine")
local RoleAttr = require("role.RoleAttr")
local CombatDefine = require("combat.CombatDefine")
local CombatBuff = require("combat.CombatBuff")
local BeSkill = require("combat.BeSkill")
local CombatImpl = require("combat.CombatImpl")

objs	= objs or {} 		-- [pos]->obj
helps	= helps or {}
-- 初始化
function initAfterStart()
	for pos = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
		local attr = {}					-- 最终属性
		RoleAttr.initCombatAttr(attr)
	
		local initAttr = {}				-- 默认属性
		RoleAttr.initCombatAttr(initAttr)

		local sysAttr = {}				-- 战前附加系统属性（比如地牢，被动技能）
		RoleAttr.initCombatAttr(sysAttr)
		
		local bufferAttr = {}		
		RoleAttr.initCombatAttr(bufferAttr)	

		local bufferAttr2 = {}		
		local obj 			= {}
		objs[pos] 			= obj
		obj.pos				= pos
		obj.helpType		= CombatDefine.HELP_TYPE0
		obj.side			= pos > CombatDefine.COMBAT_HERO_CNT and CombatDefine.DEFEND_SIDE or CombatDefine.ATTACK_SIDE
		obj.backupPos		= nil
		obj.beBackup		= nil
		obj.id				= nil
		obj.type			= nil
		obj.quality			= nil
		obj.hp				= nil
		obj.mp				= nil
		obj.initHp			= nil
		obj.initMp			= nil
		obj.job				= nil
		obj.body 			= nil
		obj.dietime			= nil
		obj.dieSkill		= nil
		obj.dieAtkCnt		= nil
		obj.camp 			= nil
        obj.sex 			= nil
		obj.attr 			= attr		
		obj.initAttr 		= initAttr
		obj.sysAttr			= sysAttr
		obj.bufferAttr		= bufferAttr
		obj.bufferAttr2		= bufferAttr2
		obj.buffer = {[0] = 0}
		obj.bufferCmd = {}		--控制类buffer
		obj.skillList		= nil
		obj.beSkillList = nil
		obj.paramData = {}
		obj.result = {0,0,0,0}		--战斗中输出和治疗 承受伤害 出手回合数 汇总
		obj.combatResult = {0,0,{},0,{}}	--每次攻击造成的伤害和治疗
		obj.extraCombatRecord = nil --战斗中额外统计的数据
		obj.delayAddBuffer = nil
		obj.normalTarget = nil
	end
	
	for pos = 1,CombatDefine.COMBAT_HELP_ALL_CNT do
		local help = {}
		local attr = {}					-- 最终属性
		RoleAttr.initCombatAttr(attr)
		help.attr = attr
		helps[pos + CombatDefine.COMBAT_HERO_ALL_CNT] = help
		help.pos = pos + CombatDefine.COMBAT_HERO_ALL_CNT
		help.helpType		= pos%CombatDefine.COMBAT_HELP_CNT
		help.id = nil
		help.side = pos > CombatDefine.COMBAT_HELP_CNT and CombatDefine.DEFEND_SIDE or CombatDefine.ATTACK_SIDE
		help.skillList = nil
		help.beSkillList = nil
		help.lv = 0
		help.head = 0
		help.body = 0
		help.quality = 0
		help.result = {0,0,0,0}		--战斗中输出和治疗 承受伤害 出手回合数 汇总
		help.combatResult = {0,0,{},0,{}}	--每次攻击受到的伤害和治疗
		help.extraCombatRecord = nil --战斗中额外统计的数据
		help.isPet = help.helpType == 1
	end
end

function getObjByPos(pos)
	if pos <= CombatDefine.COMBAT_HERO_ALL_CNT then
		return objs[pos]
	else
		return helps[pos]
	end
end

function init(obj)
	obj.id			= nil
	obj.type			= nil
	obj.quality			= nil
	obj.hp				= nil
	obj.initHp			= nil
	obj.initMp			= nil
	obj.job				= nil
	obj.body 			= nil
	obj.beSkillList = nil
	obj.skillList = nil
	obj.delayAddBuffer = nil
	obj.backupPos		= nil
	obj.beBackup		= nil
	obj.dietime			= nil
	obj.dieSkill		= nil
	obj.dieAtkCnt		= nil
	obj.camp 			= nil
    obj.sex 			= nil
	obj.normalTarget 	= nil
    obj.notSkillBaoJi	= nil
    obj.notBaoJi        = nil	
	for k in pairs(obj.buffer) do
		obj.buffer[k] = nil
	end
	obj.buffer[0] = 0
	for k,v in pairs(obj.bufferCmd) do
		obj.bufferCmd[k] = nil
	end 
		

	for k,v in pairs(obj.paramData) do
		obj.paramData[k] = nil
	end

	for k in pairs(obj.bufferAttr2) do
		obj.bufferAttr2[k] = nil
	end

	obj.result[1] = 0
	obj.result[2] = 0
	obj.result[3] = 0
	obj.result[4] = 0 
	obj.combatResult[1] = 0
	obj.combatResult[2] = 0
	for k in pairs(obj.combatResult[3]) do
		obj.combatResult[3][k] = nil 
	end
	for k in pairs(obj.combatResult[5]) do
		obj.combatResult[5][k] = nil 
	end
	obj.extraCombatRecord = nil
	RoleAttr.initCombatAttr(obj.attr)
	RoleAttr.initCombatAttr(obj.initAttr)
	RoleAttr.initCombatAttr(obj.sysAttr)
	RoleAttr.initCombatAttr(obj.bufferAttr)
end

--辅助对象相关
function initHelp(help)
	help.id = nil
	help.skillList = nil
	help.beSkillList = nil

	help.lv = 0
	help.quality = 0
	help.head = 0
	help.body = 0
    help.icon = 0
	help.result[1] = 0
	help.result[2] = 0
	help.result[3] = 0
	help.result[4] = 0
	help.combatResult[1] = 0
	help.combatResult[2] = 0
	for k in pairs(help.combatResult[3]) do
		help.combatResult[3][k] = nil 
	end
	for k in pairs(help.combatResult[5]) do
		help.combatResult[5][k] = nil 
	end
	help.extraCombatRecord = nil
	RoleAttr.initCombatAttr(help.attr) 	
end

function setInitAttr(obj, attr)
	local initAttr = obj.initAttr
	for key in pairs(initAttr) do
		initAttr[key] = attr[key] or 0
	end
	calcAttr(obj)
end

NO_LIMIT_KEY = {
	[RoleDefine.ATK_RATE] = 1,
	[RoleDefine.DEF_RATE] = 1,
    [RoleDefine.HP_ADD_RATE] = 1,
    [RoleDefine.ZAOCHENG_HP_ADD_RATE] = 1,    
}

local function checkLimit(attr)	
	for k in pairs(attr) do
		if not NO_LIMIT_KEY[k] then
			attr[k] = attr[k] < 0 and 0 or attr[k]
		end
	end
end

local function calcFinalAttr(attr)
    attr[RoleDefine.ATK] = attr[RoleDefine.ATK] * (1 + attr[RoleDefine.ATK_RATE]/10000)
	attr[RoleDefine.SPEED] = attr[RoleDefine.SPEED] * (1 + attr[RoleDefine.SPEED_RATE]/10000)
end
function calcAttr(obj)
	RoleAttr.initCombatAttr(obj.attr)

	local attr		= obj.attr
	local initAttr 	= obj.initAttr
	local sysAttr 	= obj.sysAttr
	local bufferAttr= obj.bufferAttr
	local bufferAttr2 = obj.bufferAttr2
	
	for key, val in pairs(initAttr) do
		attr[key] = val
	end

	for key ,val in pairs(bufferAttr) do
		attr[key] = attr[key] + val
	end

	for k ,v in pairs(bufferAttr2) do
		for key,val in pairs(v) do
			attr[key] = attr[key] + val
		end
	end
	
	for key ,val in pairs(sysAttr) do
		attr[key] = attr[key] + val
	end

	calcFinalAttr(attr)
	checkLimit(attr)
end

function getHpMax(obj)
	if not obj then return end
	if not obj.attr then return end
	local hpMax = obj.attr[RoleDefine.HP]
	hpMax = math.ceil(hpMax * (1 + obj.attr[RoleDefine.HP_RATE]/10000))
	return hpMax
end

function onHpCB(obj,d, attackPos,skillID)
	if d == 0 then return end 
	if obj.hp <= 0 then
		BeSkill.onDie(obj, d, attackPos)
		obj.dietime = os.time()
		obj.dieSkill = skillID
		obj.dieAtkCnt = CombatImpl.totalAtkCnt
		CombatBuff.onExtraCombatRecord(attackPos,1,"kill")
	else
		BeSkill.onHp(obj, d, attackPos)
	end

    if d < 0 then
       updateValue(obj, RoleDefine.RATE_COMBAT_NOW, -d)
    end
end
--获取伤害抵减
local function getDijianHurtRate(obj)
	local rate = 0
	rate = rate + getValue(obj,RoleDefine.FANSHE_ZHUANGJIA)
	return rate
end


local function beforeUpdateHp(obj,sum)
   if BeSkill.beforeUpdateHp(obj,sum) then
   	  return
   end
   if CombatBuff.beforeUpdateHp(obj,sum) then
   	  return
   end

   --世界boss模式 不掉血量
   if CombatImpl.fightMode[1] == CombatDefine.FIGHT_MODE3 and obj.type == CombatDefine.COMBAT_OBJ_TYPE3 then
      return
   end

   return true
end

--血量改变类型
SKILL_HP_TYPE = 1
EXTRA_HP_TYPE = 2
BUFFER_HP_TYPE = 3
function updateHp(obj, value,isRevive,delayCB, attackPos,type)
	if obj.helpType ~= CombatDefine.HELP_TYPE0 then
		return 0
	end

	if obj.hp <= 0 and not isRevive then
		return 0
	end

    -- 加血变成减血
    if value > 0 then
       value = BeSkill.beforeMinusHp(obj, value)
    end

	--反射装甲buff对技能，额外伤害的抵减
	local dijianHurt = 0
	local dijianHurtRate = getDijianHurtRate(obj)
	if value < 0 and dijianHurtRate > 0 then
		if type == SKILL_HP_TYPE or type == EXTRA_HP_TYPE then
			dijianHurt =  value * dijianHurtRate/10000
			value = value - dijianHurt
		end
	end

	if value == 0 then
		value = 1
	elseif value < 0 then
		value = math.floor(value)
	else
		value = math.ceil(value )
	end

	if type == SKILL_HP_TYPE then
		value = CombatBuff.checkBaohu(obj,value)
	end
	local sum = obj.hp + value

	-- 护盾值检测
	if value < 0 then
		local huDunValue = CombatBuff.getBuffHuDun(obj)
		if huDunValue > 0 then
			if huDunValue >= (-value) then
				sum = sum + (-value)
				CombatBuff.updateHuDun(obj, value)				
			else
				sum = sum + huDunValue
				CombatBuff.updateHuDun(obj, -huDunValue)
			end
		end
	end

	local hpMax = getHpMax(obj) 
	if sum > hpMax then
		sum = hpMax
	end

	local d = sum - obj.hp
	if d < 0 then
		local hurt = -d
		if hurt > obj.hp then
			hurt = obj.hp
		end
		d = -hurt
	end


	if sum < 0 then
		sum = 0
	end
	local ret = beforeUpdateHp(obj,sum)
	if ret then
		obj.hp = sum
	end

	if not delayCB then
		onHpCB(obj,d, attackPos)
	end
--[[	if attackPos > 12 or obj.pos > 12 then
		print(" moshou  hurt ", d , obj.pos ,attackPos)
	end
]]--
	if attackPos and d < 0 then	
		CombatImpl.setObjBearResult(obj, d)
	end
	if isRevive == true and d > 0 then
		CombatImpl.setObjResult(obj.pos, d)
	elseif attackPos then
		CombatImpl.setObjResult(attackPos, d)
	end

	if d > 0 then
		obj.combatResult[2] = obj.combatResult[2] + d
	else
		obj.combatResult[1] = obj.combatResult[1] + d
	end

	if attackPos then
		obj.combatResult[3][attackPos] = obj.combatResult[3][attackPos] or {}
		if dijianHurt > 0 then
			obj.combatResult[3][attackPos][2] = obj.combatResult[3][attackPos][2] or 0
			obj.combatResult[3][attackPos][2] = obj.combatResult[3][attackPos][2] + dijianHurt
		elseif dijianHurt < 0 then
			obj.combatResult[3][attackPos][1] = obj.combatResult[3][attackPos][1] or 0
			obj.combatResult[3][attackPos][1] = obj.combatResult[3][attackPos][1] + dijianHurt
		end

		local attacker = CombatImpl.objList[attackPos]
		if attacker and d < 0 then
			attacker.combatResult[4] = attacker.combatResult[4] + d
			attacker.combatResult[5] = attacker.combatResult[5] or {}
			attacker.combatResult[5][obj.pos] = d
			if type == EXTRA_HP_TYPE then
				updateValue(attacker, RoleDefine.HURT_COMBAT_NOW, -d)
			end
		end
	end

	return d,value
end

function updateMp(obj, value)
	value = math.floor(value + 0.5)
	local sum = obj.mp + value
	sum = sum < 0 and 0 or sum
	local d = sum - obj.mp
	obj.mp = sum
	return d	
end

function getValue(obj,key)
	if obj.isPet then
		return 0
	end
	return obj.attr[key] or 0
end

function setValue(obj,key,value)
	obj.attr[key] = value
end

function updateValue(obj,key,value)
	obj.attr[key] = obj.attr[key] or 0
	obj.attr[key] = obj.attr[key] + value
end

function getJobHurtRate(attacker,defender)
	local attr = attacker.attr
	
	--职业相关伤害加成
	local extraHurtRate = 0
	if defender.job == CombatDefine.JOB_TYPE1 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.JOB_HURT_RATE1]
	elseif defender.job == CombatDefine.JOB_TYPE2 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.JOB_HURT_RATE2]
	elseif defender.job == CombatDefine.JOB_TYPE3 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.JOB_HURT_RATE3]
	elseif defender.job == CombatDefine.JOB_TYPE4 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.JOB_HURT_RATE4]
	elseif defender.job == CombatDefine.JOB_TYPE5 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.JOB_HURT_RATE5]
	end
	
	-- 物理/魔法伤害加成
	if attacker.hurtType == CombatDefine.PHY_HURT_TYPE  then
		extraHurtRate = extraHurtRate + (attr[RoleDefine.PHY_HURT_ADD_RATE] or 0)

        extraHurtRate = extraHurtRate + (defender.attr[RoleDefine.AT_PHY_HURT_ADD_RATE] or 0)

	elseif attacker.hurtType == CombatDefine.MAGIC_HURT_TYPE then
		extraHurtRate = extraHurtRate + (attr[RoleDefine.MAGIC_HURT_ADD_RATE] or 0)

        extraHurtRate = extraHurtRate + (defender.attr[RoleDefine.AT_MAGIC_HURT_ADD_RATE] or 0)
	end
	
	return extraHurtRate
end

function getStatusHurtRate(attacker,defender)
	local status = CombatBuff.getStatus(defender)
	local attr = attacker.attr
	
	--状态相关伤害加成
	local extraHurtRate = 0
	if status["xuanyun"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE1]
	end
	if status["shihua"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE2]
	end
	if status["bingdong"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE3]
	end
	if status["jinmo"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE4]
	end
	if status["ranshao"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE5]
	end
	if status["liuxue"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE6]
	end
	if status["zhongdu"] then
		extraHurtRate = extraHurtRate + attr[RoleDefine.STATUS_HURT_RATE7]
	end
	return extraHurtRate
end

function getStatusBaoji(attacker,defender)
	local status = CombatBuff.getStatus(defender)
	local attr = attacker.attr
	--状态相关暴击率增加
	local baoji = 0
	if status["xuanyun"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE1]
	end
	if status["shihua"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE2]
	end
	if status["bingdong"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE3]
	end
	if status["jinmo"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE4]
	end
	if status["ranshao"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE5]
	end
	if status["ranshao1"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE5]
	end
	if status["liuxue"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE6]
	end
	if status["zhongdu"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE7]
	end
	if status["jiansu"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_RATE8]
	end
	return baoji
end

function getStatusBaojiHurtRate(attacker,defender)
	local status = CombatBuff.getStatus(defender)
	local attr = attacker.attr
	--状态相关暴击率增加
	local baoji = 0
	if status["xuanyun"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE1]
	elseif status["shihua"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE2]
	elseif status["bingdong"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE3]
	elseif status["jinmo"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE4]
	elseif status["ranshao"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE5]
	elseif status["ranshao1"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE5]
	elseif status["liuxue"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE6]
	elseif status["zhongdu"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE7]
	elseif status["jiansu"] then
		baoji = baoji + attr[RoleDefine.STATUS_BAOJI_HURT_RATE8]
	end
	return baoji
end

function getJobJianshangRate(attacker,defender)
	local job = attacker.job
	local attr = defender.attr
	local jianshangRate = 0
	--职业相关伤害加成
	if job == CombatDefine.JOB_TYPE1 then
		jianshangRate = jianshangRate + attr[RoleDefine.JOB_JIANSHANG_RATE1]
	elseif job == CombatDefine.JOB_TYPE2 then
		jianshangRate = jianshangRate + attr[RoleDefine.JOB_JIANSHANG_RATE2]
	elseif job == CombatDefine.JOB_TYPE3 then
		jianshangRate = jianshangRate + attr[RoleDefine.JOB_JIANSHANG_RATE3]
	elseif job == CombatDefine.JOB_TYPE4 then
		jianshangRate = jianshangRate + attr[RoleDefine.JOB_JIANSHANG_RATE4]
	elseif job == CombatDefine.JOB_TYPE5 then
		jianshangRate = jianshangRate + attr[RoleDefine.JOB_JIANSHANG_RATE5]
	end

	return jianshangRate
end

function getCampJianshangRate(attacker,defender)
	local camp = attacker.camp
	local attr = defender.attr
	local jianshangRate = 0
	--阵营相关减伤
	if camp == CombatDefine.CAMP_TYPE1 then
		jianshangRate = jianshangRate + attr[RoleDefine.CAMP_JIANSHANG_RATE1]
	elseif camp == CombatDefine.CAMP_TYPE2 then
		jianshangRate = jianshangRate + attr[RoleDefine.CAMP_JIANSHANG_RATE2]
	elseif camp == CombatDefine.CAMP_TYPE3 then
		jianshangRate = jianshangRate + attr[RoleDefine.CAMP_JIANSHANG_RATE3]
	elseif camp == CombatDefine.CAMP_TYPE4 then
		jianshangRate = jianshangRate + attr[RoleDefine.CAMP_JIANSHANG_RATE4]
	elseif camp == CombatDefine.CAMP_TYPE5 then
		jianshangRate = jianshangRate + attr[RoleDefine.CAMP_JIANSHANG_RATE5]
	end
	return jianshangRate
end

function getCampHurtRate(attacker,defender)
	local attr = attacker.attr
	
	--阵营相关伤害加成
	local extraHurtRate = 0
	if defender.camp == CombatDefine.CAMP_TYPE1 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.CAMP_HURT_RATE1]
	elseif defender.camp == CombatDefine.CAMP_TYPE2 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.CAMP_HURT_RATE2]
	elseif defender.camp == CombatDefine.CAMP_TYPE3 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.CAMP_HURT_RATE3]
	elseif defender.camp == CombatDefine.CAMP_TYPE4 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.CAMP_HURT_RATE4]
	elseif defender.camp == CombatDefine.CAMP_TYPE5 then
		extraHurtRate = extraHurtRate + attr[RoleDefine.CAMP_HURT_RATE5]
	end
	return extraHurtRate
end